package emitter

import (
	"mi/compiler/ast"
	"mi/compiler/checker"
	"mi/compiler/diagnostic"
	"mi/compiler/host"
	"mi/compiler/performance"
	"mi/internal/xpath"
	"path/filepath"
)

type Program interface {
	GetPackagePath(pkg *ast.Package) string
	GetProjectSourceFiles(pro *ast.ProjectFile) []*ast.SourceFile

	GetCompilerHost() host.CompilerHost
	GetEmitResolver() checker.EmitResolver
}

type EmitResult struct {
	EmitSkipped bool
	// Contains declaration emit diagnostics
	Diagnostics []*diagnostic.Diagnostic
	// Array of files the compiler wrote to disk
	EmittedFiles []xpath.URI

	// Array of sourceMapData if compiler emitted sourcemaps
	SourceMaps []*SourceMapData  // internal
}

type Emitter interface {
	EmitProjects(pros []*ast.ProjectFile) EmitResult
}

type emitter struct {
	program      Program
	compilerHost host.CompilerHost
	resolver     checker.EmitResolver
	diagnostics  []*diagnostic.Diagnostic
}

func Emit(program Program, project *ast.ProjectFile) EmitResult {
	var e = new(emitter)
	e.program = program
	e.compilerHost = program.GetCompilerHost()
	e.resolver = program.GetEmitResolver()

	performance.Mark("beforeEmit")
	// Clean emit files
	cleanFolder(filepath.Join(project.OutputPath, "project", "src", "main", "java"))

	var emittedFiles []xpath.URI
	var files = e.program.GetProjectSourceFiles(project)
	for _, file := range files {
		e.diagnostics = append(e.diagnostics, emitSourceFile(file, e)...)
		emittedFiles = append(emittedFiles, file.Uri)
	}
	performance.Mark("afterEmit")
	performance.Measure("Emit", "beforeEmit", "afterEmit")

	return EmitResult{
		Diagnostics:  e.diagnostics,
		EmittedFiles: emittedFiles,
	}
}



